#ifndef __THREAD_POOL_HPP__
#define __THREAD_POOL_HPP__

#pragma once
#include <iostream>
#include <string>
#include <pthread.h>
#include <vector>
#include "Thread.hpp"
#include <queue>
#include "Log.hpp"
using namespace ThreadModule;

const int g_threadnum = 5;

template <class T>
class ThreadPool
{
    private:
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }
    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void ThreadWakeupAll()
    {
        pthread_cond_broadcast(&_cond);
    }

    ThreadPool(int threadnum = g_threadnum)
    :_threadnum(threadnum),_waitnum(0),_isrunning(false)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        LOG(INFO,"ThreadPool Construct()\n");
    }
    void InitThreadPool()
    {
        //创建出所有的线程，但是不启动
        for(int i = 0;i < _threadnum; ++i)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            _threads.emplace_back(std::bind(&ThreadPool::HandlerTask,this,std::placeholders::_1),name);
            //这里需要传两个参数，HandleTask和name，
            LOG(INFO,"init thread %s done\n",name.c_str());
        }
        _isrunning = true;
    }
    void Start()
    {
        for(auto& e :_threads)
        {
            e.Start();
        }
    }
    //单例类禁用拷贝和赋值
    ThreadPool<T>& operator=(const ThreadPool<T>& ) = delete;
    ThreadPool(const ThreadPool<T>&) = delete;
public:
    static ThreadPool<T>* GetInstance()
    {
        if(nullptr == _instance)
        {
            _instance = new ThreadPool<T>();
            _instance->InitThreadPool();
            _instance->Start();

            LOG(DEBUG,"创建线程池单例\n");
            return _instance;
        }
        LOG(DEBUG,"获取线程池单例\n");
        return _instance;
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        LOG(INFO,"ThreadPool Deconstruct()\n");
    }
    //最终每一个进程都在执行这个函数
    void HandlerTask(std::string name)
    {
        while(1)
        {
            LockQueue();
            //1.队列没有任务，但是多线程在运行
            while(_task_queue.empty() && _isrunning)
            {
                //就需要让多线程休眠
                ++_waitnum;
                ThreadSleep();
                --_waitnum;
            }

            //2.队列中没有任务，同时线程池已经退出
            if(_task_queue.empty() && !_isrunning)
            {
                UnlockQueue();
                break;//线程退出，这个线程就没有必要存在了
            }

            //3.队列中有任务，但是线程池已经false了---就继续让当前这个线程处理任务
            //4.队列中有任务，线程池也是true
            T t = _task_queue.front();
            _task_queue.pop();
            UnlockQueue();

            //处理任务
            t();
            
        }
    }

    void Stop()
    {   LockQueue();
        _isrunning = false;

        ThreadWakeupAll();
        UnlockQueue();
    }
    void Wait()
    {
        for(auto& e:_threads)
        {
            e.Join();
            LOG(INFO,"%s is quit....\n",e.name().c_str());
        }
    }
    bool Enqueue(const T& in)
    {   
        bool ret = false;
        LockQueue();
        if(_isrunning)
        {
            _task_queue.push(in);
            if(_waitnum > 0)
            {
                ThreadWakeup();
            }
            LOG(DEBUG,"enqueue task success\n");
            ret = true;
        }
        UnlockQueue();
        return ret;
    }
private:
    int _threadnum;//线程池中线程的数量
    std::vector<Thread> _threads; //多线程
    std::queue<T> _task_queue;//任务队列
    pthread_mutex_t _mutex;//用来互斥访问任务队列
    pthread_cond_t _cond;//条件变量提供同步机制

    bool _isrunning;//多线程是否运行
    int _waitnum;//等待线程的数量

    static ThreadPool<T>* _instance;
    //加锁，因为创建单例的过程是互斥的。
    static pthread_mutex_t _lock;
};

template<class T>
ThreadPool<T> * ThreadPool<T>::_instance = nullptr;

template<class T>
pthread_mutex_t ThreadPool<T>::_lock = PTHREAD_MUTEX_INITIALIZER;


#endif